<!DOCTYPE html>
<html lang="zh" data-direction="ltr">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta
      name="keywords"
      content="Go-Micro, Micro, 中文, Go-Micro教程, Go-Micro资源"
    />
    <meta
      name="description"
      content="Micro 中国站，只为原生中文资源"
    />
    <title>GRPC 网关 - Micro 中国</title>
    <meta data-rh="true" property="og:type" content="website"/><meta data-rh="true" property="og:image" content=""/><meta data-rh="true" property="og:title" content="GRPC 网关 - Micro 中国"/><meta data-rh="true" name="description" content="本篇主要帮助大家在 go-micro 服务中使用 grpc 网关。"/>
    <link
      rel="icon"
      href="https://avatars2.githubusercontent.com/u/20906580?s=60&v=4"
      type="image/x-icon"
    />
    
    <link rel="stylesheet" type="text/css" href="/index-47dfeecd.css" />
    
    <style id="nprogress-style">
      #nprogress {
        display: none;
      }
    </style>
    <link rel="stylesheet/less" type="text/css" href="/color.less" />
    <script src="https://polyfill.alicdn.com/polyfill.min.js?features=default,es2015,Intl"></script>
    <script>
      (function () {
        function isLocalStorageNameSupported() {
          var testKey = 'test';
          var storage = window.localStorage;
          try {
            storage.setItem(testKey, '1');
            storage.removeItem(testKey);
            return true;
          } catch (error) {
            return false;
          }
        }
        // 优先级提高到所有静态资源的前面，语言不对，加载其他静态资源没意义
        var pathname = location.pathname;

        function isZhCN(pathname) {
          return /-cn\/?$/.test(pathname);
        }
        function getLocalizedPathname(path, zhCN) {
          var pathname = path.startsWith('/') ? path : '/' + path;
          if (!zhCN) {
            // to enUS
            return /\/?index-cn/.test(pathname) ? '/' : pathname.replace('-cn', '');
          } else if (pathname === '/') {
            return '/index-cn';
          } else if (pathname.endsWith('/')) {
            return pathname.replace(/\/$/, '-cn/');
          }
          return pathname + '-cn';
        }

        // 兼容旧的 URL， `?locale=...`
        var queryString = location.search;
        if (queryString) {
          var isZhCNConfig = queryString.indexOf('zh-CN') > -1;
          if (isZhCNConfig && !isZhCN(pathname)) {
            location.pathname = getLocalizedPathname(pathname, isZhCNConfig);
          }
        }

        // 首页无视链接里面的语言设置 https://github.com/ant-design/ant-design/issues/4552
        if (isLocalStorageNameSupported() && (pathname === '/' || pathname === '/index-cn')) {
          var lang =
            (window.localStorage && localStorage.getItem('locale')) ||
            ((navigator.language || navigator.browserLanguage).toLowerCase() === 'zh-cn'
              ? 'zh-CN'
              : 'en-US');
          // safari is 'zh-cn', while other browser is 'zh-CN';
          if ((lang === 'zh-CN') !== isZhCN(pathname)) {
            location.pathname = getLocalizedPathname(pathname, lang === 'zh-CN');
          }
        }
        document.documentElement.className += isZhCN(pathname) ? 'zh-cn' : 'en-us';
      })();
    </script>
  </head>
  <body>
    <div id="react-content">
      <div class="page-wrapper"><header id="header" class="clearfix"><div class="ant-row" style="flex-flow:nowrap;height:64px"><div class="ant-col ant-col-xs-24 ant-col-sm-24 ant-col-md-6 ant-col-lg-6 ant-col-xl-5 ant-col-xxl-4"><h1><a id="logo" href="/index-cn"><img alt="logo" src=""/>Micro 中国</a></h1></div><div class="ant-col menu-row ant-col-xs-0 ant-col-sm-0 ant-col-md-18 ant-col-lg-18 ant-col-xl-19 ant-col-xxl-20"><div id="search-box" class=""><span role="img" aria-label="search" class="anticon anticon-search"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="search" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"></path></svg></span><input type="text" placeholder="在 Micro China 中搜索" class="ant-input" value=""/></div><ul class="ant-menu menu-site ant-menu-light ant-menu-root ant-menu-horizontal" id="nav" direction="ltr" role="menu"><li class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none" role="menuitem"><div class="ant-menu-submenu-title" role="button" aria-expanded="false" aria-haspopup="true"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li class="ant-menu-item ant-menu-item-only-child" role="menuitem"><a href="/docs/micro/introduce-cn">文档</a></li><li class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none" role="menuitem"><div class="ant-menu-submenu-title" role="button" aria-expanded="false" aria-haspopup="true"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li class="ant-menu-item ant-menu-item-only-child" role="menuitem"><a href="/components/button-cn/">插件</a></li><li class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none" role="menuitem"><div class="ant-menu-submenu-title" role="button" aria-expanded="false" aria-haspopup="true"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li class="ant-menu-item ant-menu-item-only-child" role="menuitem"><a href="/docs/resources-cn">资源</a></li><li class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="visibility:hidden;position:absolute" role="menuitem"><div class="ant-menu-submenu-title" role="button" aria-expanded="false" aria-haspopup="true"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li></ul><button type="button" class="ant-btn header-button header-lang-button ant-btn-sm">繁体中文</button><button type="button" class="ant-btn header-button ant-dropdown-trigger ant-btn-sm">更多<span role="img" aria-label="down" style="font-size:9px;margin-left:2px;vertical-align:middle;margin-top:-1px" class="anticon anticon-down"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></span></button><span id="github-btn" class="github-btn"><a class="gh-btn" href="//github.com/micro/go-micro/" target="_blank"><span class="gh-ico" aria-hidden="true"></span><span class="gh-text">Star</span></a><a class="gh-count" target="_blank" href="//github.com/micro/go-micro/stargazers/"></a></span></div></div></header><div class="main-wrapper"><div class="ant-row"><div class="ant-col main-menu ant-col-xs-24 ant-col-sm-24 ant-col-md-6 ant-col-lg-6 ant-col-xl-5 ant-col-xxl-4"><div><div class=""><section class="main-menu-inner"><ul class="ant-menu aside-container menu-site ant-menu-light ant-menu-root ant-menu-inline" direction="ltr" role="menu"></ul></section></div></div></div><div class="ant-col ant-col-xs-24 ant-col-sm-24 ant-col-md-18 ant-col-lg-18 ant-col-xl-19 ant-col-xxl-20"><section class="main-container"><article class="markdown"><div><h1>GRPC 网关<a class="edit-button" href="https://github.com/ant-design/ant-design/edit/master/docs/micro/grpc-gateway.zh-CN.md" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="edit" class="anticon anticon-edit"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="edit" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z"></path></svg></span></a></h1></div><div class="toc-affix"><div class=""><ul class="toc"><li><a class="bisheng-toc-h2" href="#代码" title="代码">代码</a></li><li><a class="bisheng-toc-h2" href="#预置条件" title="预置条件">预置条件</a></li><li><a class="bisheng-toc-h2" href="#Greeter-Service" title="Greeter Service">Greeter Service</a></li><li><a class="bisheng-toc-h2" href="#GRPC-Gateway" title="GRPC Gateway">GRPC Gateway</a></li><li><a class="bisheng-toc-h2" href="#运行示例" title="运行示例">运行示例</a></li><li><a class="bisheng-toc-h2" href="#局限性" title="局限性">局限性</a></li></ul></div></div><section class="markdown"><p>本篇主要帮助大家在 go-micro 服务中使用 grpc 网关。</p><p>GRPC 网关<a href="https://github.com/grpc-ecosystem/grpc-gateway">grpc-gateway</a>是<a href="http://github.com/google/protobuf">protoc</a>的一个插件。它遵循<a href="http://github.com/grpc/grpc-common">gRPC</a>中的服务定义，生成反向代理服务，这个代理就会把 RESTful 风格的 JSON API 转成 gRPC 请求。</p><p>我们使用<a href="https://github.com/micro/go-grpc">go-grpc</a>写后台服务。Go-GRPC 是客户端与服务端的 go-micro、grpc 插件包装器。当调用<a href="https://godoc.org/github.com/micro/go-grpc#NewService">grpc.NewService</a>时，它会返回<a href="https://pkg.go.dev/github.com/micro/go-micro/v2#Service">micro.Service</a>服务。</p><h2 id="代码"><span>代码</span><a href="#代码" class="anchor">#</a></h2><p>可以在<a href="https://github.com/micro/examples/tree/master/grpc">examples/grpc</a>中查找相关代码。</p><h2 id="预置条件"><span>预置条件</span><a href="#预置条件" class="anchor">#</a></h2><p>我们需要下面准备工作：</p><h3 id="安装-protobuf"><span>安装 protobuf</span><a href="#安装-protobuf" class="anchor">#</a></h3><pre class="language-null"><code>mkdir tmp
cd tmp
git clone https<span class="token punctuation">:</span><span class="token operator">/</span><span class="token operator">/</span>github<span class="token punctuation">.</span>com<span class="token operator">/</span>google<span class="token operator">/</span>protobuf
cd protobuf
<span class="token punctuation">.</span><span class="token operator">/</span>autogen<span class="token punctuation">.</span>sh
<span class="token punctuation">.</span><span class="token operator">/</span>configure
make
make check
sudo make install</code></pre><h3 id="安装插件"><span>安装插件</span><a href="#安装插件" class="anchor">#</a></h3><pre class="language-null"><code>go get <span class="token operator">-</span>u github<span class="token punctuation">.</span>com<span class="token operator">/</span>grpc<span class="token operator">-</span>ecosystem<span class="token operator">/</span>grpc<span class="token operator">-</span>gateway<span class="token operator">/</span>protoc<span class="token operator">-</span>gen<span class="token operator">-</span>grpc<span class="token operator">-</span>gateway
go get <span class="token operator">-</span>u github<span class="token punctuation">.</span>com<span class="token operator">/</span>micro<span class="token operator">/</span>protobuf<span class="token operator">/</span>protoc<span class="token operator">-</span>gen<span class="token operator">-</span>go</code></pre><h2 id="Greeter-Service"><span>Greeter Service</span><a href="#Greeter-Service" class="anchor">#</a></h2><p>例子中我们使用<a href="https://github.com/micro/go-grpc">go-grpc</a>创建了简单的<strong>greeter</strong>微服务。</p><p>下面的 proto 文件的代码：</p><pre class="language-proto"><code>syntax <span class="token operator">=</span> <span class="token string">"proto3"</span><span class="token comment" spellcheck="true">;</span>

package go<span class="token punctuation">.</span>micro<span class="token punctuation">.</span>srv<span class="token punctuation">.</span>greeter<span class="token comment" spellcheck="true">;</span>

service Say {
	rpc <span class="token function">Hello</span><span class="token punctuation">(</span>Request<span class="token punctuation">)</span> returns <span class="token punctuation">(</span>Response<span class="token punctuation">)</span> {}
}

message Request {
	string name <span class="token operator">=</span> <span class="token number">1</span><span class="token comment" spellcheck="true">;</span>
}

message Response {
	string msg <span class="token operator">=</span> <span class="token number">1</span><span class="token comment" spellcheck="true">;</span>
}</code></pre><p>服务的 Go 代码：</p><pre class="language-null"><code>package main

import <span class="token punctuation">(</span>
	<span class="token string">"log"</span>
	<span class="token string">"time"</span>

	hello <span class="token string">"github.com/micro/examples/greeter/srv/proto/hello"</span>
	<span class="token string">"github.com/micro/go-grpc"</span>
	<span class="token string">"github.com/micro/go-micro/v2"</span>

	<span class="token string">"golang.org/x/net/context"</span>
<span class="token punctuation">)</span>

type Say struct{}

<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>Say<span class="token punctuation">)</span> <span class="token function">Hello</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> req <span class="token operator">*</span>hello<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> rsp <span class="token operator">*</span>hello<span class="token punctuation">.</span>Response<span class="token punctuation">)</span> error {
	log<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span><span class="token string">"Received Say.Hello request"</span><span class="token punctuation">)</span>
	rsp<span class="token punctuation">.</span>Msg <span class="token operator">=</span> <span class="token string">"Hello "</span> <span class="token operator">+</span> req<span class="token punctuation">.</span>Name
	return nil
}

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> {
	service <span class="token punctuation">:</span><span class="token operator">=</span> grpc<span class="token punctuation">.</span><span class="token function">NewService</span><span class="token punctuation">(</span>
		micro<span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"go.micro.srv.greeter"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
		micro<span class="token punctuation">.</span><span class="token function">RegisterTTL</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">30</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
		micro<span class="token punctuation">.</span><span class="token function">RegisterInterval</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
	<span class="token punctuation">)</span>

	<span class="token operator">/</span><span class="token operator">/</span> optionally setup command line usage
	service<span class="token punctuation">.</span><span class="token function">Init</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

	<span class="token operator">/</span><span class="token operator">/</span> Register Handlers
	hello<span class="token punctuation">.</span><span class="token function">RegisterSayHandler</span><span class="token punctuation">(</span>service<span class="token punctuation">.</span><span class="token function">Server</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">new</span><span class="token punctuation">(</span>Say<span class="token punctuation">)</span><span class="token punctuation">)</span>

	<span class="token operator">/</span><span class="token operator">/</span> Run server
	<span class="token keyword">if</span> err <span class="token punctuation">:</span><span class="token operator">=</span> service<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token comment" spellcheck="true">; err != nil {</span>
		log<span class="token punctuation">.</span><span class="token function">Fatal</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
	}
}</code></pre><h2 id="GRPC-Gateway"><span>GRPC Gateway</span><a href="#GRPC-Gateway" class="anchor">#</a></h2><p>GRPC 网关使用相同的 proto 文件配上 http 选项提供服务</p><pre class="language-proto"><code>syntax <span class="token operator">=</span> <span class="token string">"proto3"</span><span class="token comment" spellcheck="true">;</span>

package greeter<span class="token comment" spellcheck="true">;</span>

import <span class="token string">"google/api/annotations.proto"</span><span class="token comment" spellcheck="true">;</span>

service Say {
	rpc <span class="token function">Hello</span><span class="token punctuation">(</span>Request<span class="token punctuation">)</span> returns <span class="token punctuation">(</span>Response<span class="token punctuation">)</span> {
		option <span class="token punctuation">(</span>google<span class="token punctuation">.</span>api<span class="token punctuation">.</span>http<span class="token punctuation">)</span> <span class="token operator">=</span> {
			post<span class="token punctuation">:</span> <span class="token string">"/greeter/hello"</span>
			body<span class="token punctuation">:</span> <span class="token string">"*"</span>
		}<span class="token comment" spellcheck="true">;</span>
	}
}

message Request {
	string name <span class="token operator">=</span> <span class="token number">1</span><span class="token comment" spellcheck="true">;</span>
}

message Response {
	string msg <span class="token operator">=</span> <span class="token number">1</span><span class="token comment" spellcheck="true">;</span>
}</code></pre><p>通过下面的 proto 命令生成 grpc 的存根和反向代理</p><pre class="language-null"><code>protoc <span class="token operator">-</span>I<span class="token operator">/</span>usr<span class="token operator">/</span><span class="token keyword">local</span><span class="token operator">/</span>include <span class="token operator">-</span>I<span class="token punctuation">.</span> \
  <span class="token operator">-</span>I<span class="token variable">$GOPATH</span><span class="token operator">/</span>src \
  <span class="token operator">-</span>I<span class="token variable">$GOPATH</span><span class="token operator">/</span>src<span class="token operator">/</span>github<span class="token punctuation">.</span>com<span class="token operator">/</span>grpc<span class="token operator">-</span>ecosystem<span class="token operator">/</span>grpc<span class="token operator">-</span>gateway<span class="token operator">/</span>third_party<span class="token operator">/</span>googleapis \
  <span class="token operator">-</span><span class="token operator">-</span>go_out<span class="token operator">=</span>plugins<span class="token operator">=</span>grpc<span class="token punctuation">:</span><span class="token punctuation">.</span> \
  path<span class="token operator">/</span><span class="token keyword">to</span><span class="token operator">/</span>your_service<span class="token punctuation">.</span>proto</code></pre><pre class="language-null"><code>protoc <span class="token operator">-</span>I<span class="token operator">/</span>usr<span class="token operator">/</span><span class="token keyword">local</span><span class="token operator">/</span>include <span class="token operator">-</span>I<span class="token punctuation">.</span> \
  <span class="token operator">-</span>I<span class="token variable">$GOPATH</span><span class="token operator">/</span>src \
  <span class="token operator">-</span>I<span class="token variable">$GOPATH</span><span class="token operator">/</span>src<span class="token operator">/</span>github<span class="token punctuation">.</span>com<span class="token operator">/</span>grpc<span class="token operator">-</span>ecosystem<span class="token operator">/</span>grpc<span class="token operator">-</span>gateway<span class="token operator">/</span>third_party<span class="token operator">/</span>googleapis \
  <span class="token operator">-</span><span class="token operator">-</span>grpc<span class="token operator">-</span>gateway_out<span class="token operator">=</span>logtostderr<span class="token operator">=</span><span class="token boolean">true</span><span class="token punctuation">:</span><span class="token punctuation">.</span> \
  path<span class="token operator">/</span><span class="token keyword">to</span><span class="token operator">/</span>your_service<span class="token punctuation">.</span>proto</code></pre><p>在下面的代码中我们写了一个简单的问候（greeter）服务 API。类似的代码也会用来注册其它的端点。切记，网关需要端点地址及服务。</p><pre class="language-null"><code>package main

import <span class="token punctuation">(</span>
	<span class="token string">"flag"</span>
	<span class="token string">"net/http"</span>

	<span class="token string">"github.com/golang/glog"</span>
	<span class="token string">"github.com/grpc-ecosystem/grpc-gateway/runtime"</span>
	<span class="token string">"golang.org/x/net/context"</span>
	<span class="token string">"google.golang.org/grpc"</span>

	hello <span class="token string">"github.com/micro/examples/grpc/gateway/proto/hello"</span>
<span class="token punctuation">)</span>

var <span class="token punctuation">(</span>
	<span class="token operator">/</span><span class="token operator">/</span> the go<span class="token punctuation">.</span>micro<span class="token punctuation">.</span>srv<span class="token punctuation">.</span>greeter address
	endpoint <span class="token operator">=</span> flag<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token string">"endpoint"</span><span class="token punctuation">,</span> <span class="token string">"localhost:9090"</span><span class="token punctuation">,</span> <span class="token string">"go.micro.srv.greeter address"</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>

<span class="token keyword">func</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> error {
	ctx <span class="token punctuation">:</span><span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	ctx<span class="token punctuation">,</span> cancel <span class="token punctuation">:</span><span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">WithCancel</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span>
	defer <span class="token function">cancel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

	mux <span class="token punctuation">:</span><span class="token operator">=</span> runtime<span class="token punctuation">.</span><span class="token function">NewServeMux</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	opts <span class="token punctuation">:</span><span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>grpc<span class="token punctuation">.</span>DialOption{grpc<span class="token punctuation">.</span><span class="token function">WithInsecure</span><span class="token punctuation">(</span><span class="token punctuation">)</span>}

	err <span class="token punctuation">:</span><span class="token operator">=</span> hello<span class="token punctuation">.</span><span class="token function">RegisterSayHandlerFromEndpoint</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> mux<span class="token punctuation">,</span> <span class="token operator">*</span>endpoint<span class="token punctuation">,</span> opts<span class="token punctuation">)</span>
	<span class="token keyword">if</span> err !<span class="token operator">=</span> nil {
		return err
	}

	return http<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span><span class="token string">":8080"</span><span class="token punctuation">,</span> mux<span class="token punctuation">)</span>
}

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> {
	flag<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

	defer glog<span class="token punctuation">.</span><span class="token function">Flush</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

	<span class="token keyword">if</span> err <span class="token punctuation">:</span><span class="token operator">=</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token comment" spellcheck="true">; err != nil {</span>
		glog<span class="token punctuation">.</span><span class="token function">Fatal</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
	}
}</code></pre><h2 id="运行示例"><span>运行示例</span><a href="#运行示例" class="anchor">#</a></h2><p>现在运行 greeter 服务，指定<code>mdns</code>参数，因为现在我们还没有注册中心。</p><pre class="language-null"><code>go run examples<span class="token operator">/</span>grpc<span class="token operator">/</span>greeter<span class="token operator">/</span>srv<span class="token operator">/</span>main<span class="token punctuation">.</span>go <span class="token operator">-</span><span class="token operator">-</span>registry<span class="token operator">=</span>mdns <span class="token operator">-</span><span class="token operator">-</span>server_address<span class="token operator">=</span>localhost<span class="token punctuation">:</span><span class="token number">9090</span></code></pre><p>运行网关程序，把 greeter 服务所有端点都放在<code>localhost:9090</code>下</p><pre class="language-null"><code>go run examples<span class="token operator">/</span>grpc<span class="token operator">/</span>gateway<span class="token operator">/</span>main<span class="token punctuation">.</span>go</code></pre><p>用 Curl 命令请求网关</p><pre class="language-null"><code>curl <span class="token operator">-</span>d <span class="token string">'{"name": "john"}'</span> http<span class="token punctuation">:</span><span class="token operator">/</span><span class="token operator">/</span>localhost<span class="token punctuation">:</span><span class="token number">8080</span><span class="token operator">/</span>greeter<span class="token operator">/</span>hello</code></pre><h2 id="局限性"><span>局限性</span><a href="#局限性" class="anchor">#</a></h2><p>我们需要向 gRPC 网关提供使用了服务发现、动态路由、负载均衡的后台 micro api 服务所在的地址。这降低了集成网关的通用性。</p><p>参考<a href="https://github.com/micro/micro">github.com/micro/micro</a>了解更多。</p></section><section class="markdown api-container"></section></article><div class="contributors-list" style="display:flex;list-style:none;margin:0;padding:0"><span style="opacity:0.3" class="ant-avatar ant-avatar-circle"><span class="ant-avatar-string" style="opacity:0"></span></span></div></section><section class="prev-next-nav"></section><footer class="rc-footer rc-footer-dark"><section class="rc-footer-container"><section class="rc-footer-columns"><div class="rc-footer-column"><h2>相关资源</h2><div class="rc-footer-item"><a href="https://github.com/micro-in-cn/platform-web" target="_blank">Platform Web 治理平台</a></div><div class="rc-footer-item"><a href="https://github.com/micro-in-cn/XConf" target="_blank">XConf 配置中心</a></div></div><div class="rc-footer-column"><h2>社区</h2><div class="rc-footer-item"><a href="https://github.com/websemantics/awesome-ant-design" target="_blank"><span class="rc-footer-item-icon"><span role="img" aria-label="comment" class="anticon anticon-comment"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="comment" width="1em" height="1em" fill="currentColor" aria-hidden="true"><defs><style></style></defs><path d="M573 421c-23.1 0-41 17.9-41 40s17.9 40 41 40c21.1 0 39-17.9 39-40s-17.9-40-39-40zm-280 0c-23.1 0-41 17.9-41 40s17.9 40 41 40c21.1 0 39-17.9 39-40s-17.9-40-39-40z"></path><path d="M894 345a343.92 343.92 0 00-189-130v.1c-17.1-19-36.4-36.5-58-52.1-163.7-119-393.5-82.7-513 81-96.3 133-92.2 311.9 6 439l.8 132.6c0 3.2.5 6.4 1.5 9.4a31.95 31.95 0 0040.1 20.9L309 806c33.5 11.9 68.1 18.7 102.5 20.6l-.5.4c89.1 64.9 205.9 84.4 313 49l127.1 41.4c3.2 1 6.5 1.6 9.9 1.6 17.7 0 32-14.3 32-32V753c88.1-119.6 90.4-284.9 1-408zM323 735l-12-5-99 31-1-104-8-9c-84.6-103.2-90.2-251.9-11-361 96.4-132.2 281.2-161.4 413-66 132.2 96.1 161.5 280.6 66 412-80.1 109.9-223.5 150.5-348 102zm505-17l-8 10 1 104-98-33-12 5c-56 20.8-115.7 22.5-171 7l-.2-.1A367.31 367.31 0 00729 676c76.4-105.3 88.8-237.6 44.4-350.4l.6.4c23 16.5 44.1 37.1 62 62 72.6 99.6 68.5 235.2-8 330z"></path><path d="M433 421c-23.1 0-41 17.9-41 40s17.9 40 41 40c21.1 0 39-17.9 39-40s-17.9-40-39-40z"></path></svg></span></span>讨论</a></div><div class="rc-footer-item"><a href="/docs/community/join-us-cn#加入我们"><span class="rc-footer-item-icon"><span role="img" aria-label="usergroup-add" class="anticon anticon-usergroup-add"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="usergroup-add" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M892 772h-80v-80c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v80h-80c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h80v80c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-80h80c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zM373.5 498.4c-.9-8.7-1.4-17.5-1.4-26.4 0-15.9 1.5-31.4 4.3-46.5.7-3.6-1.2-7.3-4.5-8.8-13.6-6.1-26.1-14.5-36.9-25.1a127.54 127.54 0 01-38.7-95.4c.9-32.1 13.8-62.6 36.3-85.6 24.7-25.3 57.9-39.1 93.2-38.7 31.9.3 62.7 12.6 86 34.4 7.9 7.4 14.7 15.6 20.4 24.4 2 3.1 5.9 4.4 9.3 3.2 17.6-6.1 36.2-10.4 55.3-12.4 5.6-.6 8.8-6.6 6.3-11.6-32.5-64.3-98.9-108.7-175.7-109.9-110.8-1.7-203.2 89.2-203.2 200 0 62.8 28.9 118.8 74.2 155.5-31.8 14.7-61.1 35-86.5 60.4-54.8 54.7-85.8 126.9-87.8 204a8 8 0 008 8.2h56.1c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5 29.4-29.4 65.4-49.8 104.7-59.7 3.8-1.1 6.4-4.8 5.9-8.8zM824 472c0-109.4-87.9-198.3-196.9-200C516.3 270.3 424 361.2 424 472c0 62.8 29 118.8 74.2 155.5a300.95 300.95 0 00-86.4 60.4C357 742.6 326 814.8 324 891.8a8 8 0 008 8.2h56c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5C505.8 695.7 563 672 624 672c110.4 0 200-89.5 200-200zm-109.5 90.5C690.3 586.7 658.2 600 624 600s-66.3-13.3-90.5-37.5a127.26 127.26 0 01-37.5-91.8c.3-32.8 13.4-64.5 36.3-88 24-24.6 56.1-38.3 90.4-38.7 33.9-.3 66.8 12.9 91 36.6 24.8 24.3 38.4 56.8 38.4 91.4-.1 34.2-13.4 66.3-37.6 90.5z"></path></svg></span></span>加入我们</a></div></div><div class="rc-footer-column"><h2>帮助</h2><div class="rc-footer-item"><a href="https://github.com/micro-in-cn/questions" target="_blank"><span class="rc-footer-item-icon"><span role="img" aria-label="github" class="anticon anticon-github"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="github" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M511.6 76.3C264.3 76.2 64 276.4 64 523.5 64 718.9 189.3 885 363.8 946c23.5 5.9 19.9-10.8 19.9-22.2v-77.5c-135.7 15.9-141.2-73.9-150.3-88.9C215 726 171.5 718 184.5 703c30.9-15.9 62.4 4 98.9 57.9 26.4 39.1 77.9 32.5 104 26 5.7-23.5 17.9-44.5 34.7-60.8-140.6-25.2-199.2-111-199.2-213 0-49.5 16.3-95 48.3-131.7-20.4-60.5 1.9-112.3 4.9-120 58.1-5.2 118.5 41.6 123.2 45.3 33-8.9 70.7-13.6 112.9-13.6 42.4 0 80.2 4.9 113.5 13.9 11.3-8.6 67.3-48.8 121.3-43.9 2.9 7.7 24.7 58.3 5.5 118 32.4 36.8 48.9 82.7 48.9 132.3 0 102.2-59 188.1-200 212.9a127.5 127.5 0 0138.1 91v112.5c.8 9 0 17.9 15 17.9 177.1-59.7 304.6-227 304.6-424.1 0-247.2-200.4-447.3-447.5-447.3z"></path></svg></span></span>GitHub</a></div></div><div class="rc-footer-column"><h2><span class="rc-footer-column-icon"><img src="https://gw.alipayobjects.com/zos/rmsportal/nBVXkrFdWHxbZlmMbsaH.svg" alt="Ant XTech"/></span>更多产品</h2><div class="rc-footer-item"><a href="https://yuque.com" target="_blank"><span class="rc-footer-item-icon"><img src="https://gw.alipayobjects.com/zos/rmsportal/XuVpGqBFxXplzvLjJBZB.svg" alt="yuque"/></span>语雀</a><span class="rc-footer-item-separator">-</span><span class="rc-footer-item-description">知识创作与分享工具</span></div></div></section></section><section class="rc-footer-bottom"><div class="rc-footer-bottom-container">Made with <span style="color:#fff">❤</span> by<!-- --> <a target="_blank" rel="noopener noreferrer" href="https://xtech.antfin.com">XTech</a></div></section></footer></div></div></div></div>
    </div>
    
    <script src="/index-c81a5111.js"></script>
    
    <!-- Global Site Tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-72788897-1"></script>
    <script>
      if (!location.port) {
        // Enable Google Analytics
        window.dataLayer = window.dataLayer || [];
        function gtag() {
          dataLayer.push(arguments);
        }
        gtag('js', new Date());
        gtag('config', 'UA-72788897-1');
      }
    </script>
    <!-- Hotjar Tracking Code for microhq.cn -->
    <script>
      (function (h, o, t, j, a, r) {
        h.hj =
          h.hj ||
          function () {
            (h.hj.q = h.hj.q || []).push(arguments);
          };
        h._hjSettings = { hjid: 1779539, hjsv: 6 };
        a = o.getElementsByTagName('head')[0];
        r = o.createElement('script');
        r.async = 1;
        r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
        a.appendChild(r);
      })(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv=');
    </script>
  </body>
</html>
